#include "plugin_manager.h"
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h> // For errno

// 包含 MPack 相关头文件 (确保路径正确)
#include "mpack/mpack.h" // 包含核心、节点、期望 API

#define INITIAL_CAPACITY 4
// #define CONFIG_FILE_EXTENSION ".mp" // 不再需要

// 辅助函数：创建目录 (保持不变)
static int create_directory(const char *path) {
#ifdef _WIN32
    return mkdir(path);
#else
    return mkdir(path, 0777);
#endif
}

// 辅助函数，复制字符串 (保持不变)
char* strdup_custom(const char *s) {
    if (!s) return NULL;
    char *d = malloc(strlen(s) + 1);
    if (!d) return NULL;
    strcpy(d, s);
    return d;
}

// --- 新函数：解析主配置文件并加载插件 ---
bool parse_main_config_and_load_plugins(PluginManager* manager, const char* config_path) {
    // 1. 读取整个配置文件到缓冲区
    FILE* fp = fopen(config_path, "rb");
    if (!fp) {
        perror("fopen");
        fprintf(stderr, "Failed to open main config file: %s\n", config_path);
        return false;
    }
    fseek(fp, 0, SEEK_END);
    long filesize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    // --- 重要：将缓冲区分配给 manager->config_buffer ---
    manager->config_buffer = (char*)malloc(filesize);
    if (!manager->config_buffer) {
        fclose(fp);
        perror("malloc");
        fprintf(stderr, "Failed to allocate memory for config buffer: %s\n", config_path);
        return false;
    }
    manager->config_buffer_size = filesize; // 记录大小

    size_t read_size = fread(manager->config_buffer, 1, filesize, fp);
    fclose(fp);

    if (read_size != (size_t)filesize) {
        free(manager->config_buffer); // 清理已分配的内存
        manager->config_buffer = NULL;
        manager->config_buffer_size = 0;
        fprintf(stderr, "Failed to read entire config file: %s\n", config_path);
        return false;
    }

    // 2. 使用 Node API 解析缓冲区内容到 MPack 树
    // 注意：树会引用 manager->config_buffer 中的数据，所以 buffer 必须在树的生命周期内有效
    mpack_tree_init_data(&manager->config_tree, manager->config_buffer, manager->config_buffer_size);
    mpack_tree_parse(&manager->config_tree);
    manager->tree_initialized = true; // 标记树已初始化

    // 检查解析错误
    if (mpack_tree_error(&manager->config_tree) != mpack_ok) {
        fprintf(stderr, "Error parsing MessagePack config file %s: %s\n",
                config_path, mpack_error_to_string(mpack_tree_error(&manager->config_tree)));
        // 不需要 destroy 树，因为 init 可能失败，但需要释放 buffer
        free(manager->config_buffer);
        manager->config_buffer = NULL;
        manager->config_buffer_size = 0;
        manager->tree_initialized = false;
        return false;
    }

    // 3. 获取根节点，并期望它是一个 Map
    mpack_node_t root = mpack_tree_root(&manager->config_tree);
    if (mpack_node_type(root) != mpack_type_map) {
         fprintf(stderr, "Error: Root of config file %s is not a map.\n", config_path);
         // 树已成功初始化，需要 destroy
         mpack_tree_destroy(&manager->config_tree);
         free(manager->config_buffer);
         manager->config_buffer = NULL;
         manager->config_buffer_size = 0;
         manager->tree_initialized = false;
         return false;
    }

    // 4. 查找 "plugins" 键对应的 Map 节点
    mpack_node_t plugins_map = mpack_node_map_cstr(root, "plugins");
    if (mpack_node_is_missing(plugins_map)) {
        fprintf(stderr, "Error: Key 'plugins' not found in config file %s.\n", config_path);
        mpack_tree_destroy(&manager->config_tree);
        free(manager->config_buffer);
        manager->config_buffer = NULL;
        manager->config_buffer_size = 0;
        manager->tree_initialized = false;
        return false;
    }
    if (mpack_node_type(plugins_map) != mpack_type_map) {
        fprintf(stderr, "Error: Value for key 'plugins' is not a map in config file %s.\n", config_path);
        mpack_tree_destroy(&manager->config_tree);
        free(manager->config_buffer);
        manager->config_buffer = NULL;
        manager->config_buffer_size = 0;
        manager->tree_initialized = false;
        return false;
    }

    // 5. 遍历 "plugins" map，加载每个插件
    size_t num_plugins = mpack_node_map_count(plugins_map);
    printf("Found %zu plugins in config.\n", num_plugins);

    for (size_t i = 0; i < num_plugins; ++i) {
        mpack_node_t key_node = mpack_node_map_key_at(plugins_map, i);
        mpack_node_t value_node = mpack_node_map_value_at(plugins_map, i); // 这个 value_node 就是插件的配置节点

        // 获取插件名 (key)
        if (mpack_node_type(key_node) != mpack_type_str) {
            fprintf(stderr, "Warning: Plugin key at index %zu is not a string. Skipping.\n", i);
            continue;
        }
        const char* plugin_name = mpack_node_str(key_node);
        size_t plugin_name_len = mpack_node_strlen(key_node);
        // 可以选择性地检查插件名长度

        printf("Attempting to load plugin '%s'...\n", plugin_name);

        // --- 调用修改后的 load_plugin ---
        // value_node (插件的配置 map 节点) 被传递给 load_plugin
        PluginHandle handle = load_plugin(manager, plugin_name, value_node);
        if (!handle) {
            fprintf(stderr, "Failed to load plugin '%s'.\n", plugin_name);
            // 根据需要决定是否继续加载其他插件
        } else {
             printf("Successfully loaded plugin '%s' with handle %p.\n", plugin_name, handle);
        }
    }

    // 注意：此时不 destroy 树和 buffer，它们需要由 destroy_plugin_manager 清理

    return true; // 表示配置文件解析和插件加载尝试完成（可能部分失败）
}


// --- 移除旧的 load_plugins_from_config ---
/*
bool load_plugins_from_config(PluginManager* manager,const char* config_path) {
    // ... 旧的实现 ...
}
*/

// --- 移除 load_plugin_config ---
/*
bool load_plugin_config(PluginManager* manager, LoadedPlugin* plugin, const char* config_file) {
    // ... 旧的实现 ...
}
*/


// 创建插件管理器
PluginManager* create_plugin_manager(const char* plugin_dir, const char* config_dir) {
    PluginManager* manager = (PluginManager*)malloc(sizeof(PluginManager));
    if (manager == NULL) {
        perror("Failed to allocate memory for PluginManager");
        return NULL;
    }

    // 初始化管理器字段
    manager->plugin_dir = strdup_custom(plugin_dir);
    manager->config_dir = strdup_custom(config_dir);
    manager->plugins = NULL;
    manager->plugin_count = 0;
    manager->plugin_capacity = 0;
    manager->config_buffer = NULL; // 初始化 MPack 相关字段
    manager->config_buffer_size = 0;
    manager->tree_initialized = false;

    if (manager->plugin_dir == NULL || manager->config_dir == NULL) {
        perror("Failed to allocate memory for directories");
        free(manager->plugin_dir); // free(NULL) is safe
        free(manager->config_dir);
        free(manager);
        return NULL;
    }

    // 创建配置文件目录
    if (create_directory(manager->config_dir) != 0 && errno != EEXIST) {
         perror("Failed to create config directory");
         free(manager->config_dir);
         free(manager->plugin_dir);
         free(manager);
         return NULL;
    }

    // 执行 python 脚本生成 config.mp (保持不变)
    printf("Converting Python config files to MessagePack...\n");
    int status = system("python3 py_to_mp.py");
    if (status != 0) { // 检查脚本执行状态
          fprintf(stderr, "Python script execution failed with status %d!\n", status);
           free(manager->config_dir);
           free(manager->plugin_dir);
           free(manager);
           return NULL;
    }

    // --- 调用新的配置解析和插件加载函数 ---
    char config_path[256];
    snprintf(config_path, sizeof(config_path), "%s/%s", manager->config_dir, "config.mp");
    if (!parse_main_config_and_load_plugins(manager, config_path)) {
        fprintf(stderr, "Failed to parse config file or load plugins. Manager creation failed.\n");
        // 清理已分配的资源 (parse 函数内部可能已部分清理)
        if (manager->tree_initialized) {
            mpack_tree_destroy(&manager->config_tree);
        }
        free(manager->config_buffer);
        free(manager->plugins); // 可能在 parse 中分配了
        free(manager->config_dir);
        free(manager->plugin_dir);
        free(manager);
        return NULL;
    }

    printf("Plugin manager created successfully.\n");
    return manager;
}

// 销毁插件管理器
void destroy_plugin_manager(PluginManager* manager) {
    if (manager) {
        printf("Destroying plugin manager...\n");
        // 1. 先卸载所有插件
        for (int i = 0; i < manager->plugin_count; ++i) {
            printf("Attempting to unload plugin %d (%s)\n", i, manager->plugins[i].info.name ? manager->plugins[i].info.name : "N/A");
            if (manager->plugins[i].state != PLUGIN_STATE_UNLOADED) {
                if (!unload_plugin(manager, manager->plugins[i].handle)) {
                    fprintf(stderr, "Warning: Failed to properly unload plugin %s\n", manager->plugins[i].info.name ? manager->plugins[i].info.name : "N/A");
                    // 即使卸载失败，也可能需要继续尝试清理其他资源
                }
            } else {
                printf("Plugin %d already unloaded or failed to load.\n", i);
                // 如果插件从未成功加载，可能需要手动释放 info 中的字符串
                if (manager->plugins[i].info.name) free((void*)manager->plugins[i].info.name);
                if (manager->plugins[i].info.description) free((void*)manager->plugins[i].info.description);
            }
        }
        // 2. 释放插件数组
        free(manager->plugins);
        manager->plugins = NULL;
        manager->plugin_count = 0;
        manager->plugin_capacity = 0;

        // 3. 销毁 MPack 树 (如果已初始化)
        if (manager->tree_initialized) {
            printf("Destroying MPack tree...\n");
            mpack_tree_destroy(&manager->config_tree);
            manager->tree_initialized = false;
        }

        // 4. 释放配置文件缓冲区
        printf("Freeing config buffer...\n");
        free(manager->config_buffer);
        manager->config_buffer = NULL;
        manager->config_buffer_size = 0;

        // 5. 释放目录字符串
        printf("Freeing directory strings...\n");
        free(manager->plugin_dir);
        free(manager->config_dir);
        manager->plugin_dir = NULL;
        manager->config_dir = NULL;

        // 6. 释放管理器本身
        printf("Freeing plugin manager structure...\n");
        free(manager);
    }
}

// 辅助函数：查找插件 (保持不变)
static LoadedPlugin* find_plugin(PluginManager* manager, PluginHandle handle) {
    for (int i = 0; i < manager->plugin_count; ++i) {
        // 确保 handle 有效且插件已加载
        if (manager->plugins[i].handle == handle && manager->plugins[i].state != PLUGIN_STATE_UNLOADED) {
            return &manager->plugins[i];
        }
    }
    return NULL;
}

// --- 修改后的 load_plugin ---
PluginHandle load_plugin(PluginManager* manager, const char* plugin_name, mpack_node_t config_node) { // 添加 config_node 参数
    char plugin_path[256];
    snprintf(plugin_path, sizeof(plugin_path), "%s/%s.so", manager->plugin_dir, plugin_name);

    // 1. 打开动态链接库 (保持不变)
    void* dl_handle = dlopen(plugin_path, RTLD_NOW);
    if (!dl_handle) {
        fprintf(stderr, "Failed to load plugin: %s, error: %s\n", plugin_path, dlerror());
        return NULL;
    }

    // 2. 获取 get_info 函数 (保持不变)
    PluginGetInfoFunc get_info = (PluginGetInfoFunc)dlsym(dl_handle, "get_plugin_info_export");
    if (!get_info) { /* ... error handling ... */ dlclose(dl_handle); return NULL; }

    // 3. 获取插件信息 (保持不变)
    PluginInfo info = get_info();
    printf("Loading plugin: %s, Description: %s, API Version: %d\n", info.name, info.description, info.api_version);

    // 4. 获取 load 函数 (保持不变)
    PluginLoadFunc load = (PluginLoadFunc)dlsym(dl_handle, "plugin_load_export");
    if (!load) { /* ... error handling ... */ dlclose(dl_handle); return NULL; }

    // 5. 执行插件的 load 函数 (保持不变)
    PluginHandle plugin_handle;
    if (!load(&plugin_handle)) { /* ... error handling ... */ dlclose(dl_handle); return NULL; }

    // 6. 检查插件数组容量 (保持不变)
    if (manager->plugin_count == manager->plugin_capacity) {
        manager->plugin_capacity = manager->plugin_capacity == 0 ? INITIAL_CAPACITY : manager->plugin_capacity * 2;
        LoadedPlugin* new_plugins_ptr = (LoadedPlugin*)realloc(manager->plugins, sizeof(LoadedPlugin) * manager->plugin_capacity);
        if (!new_plugins_ptr) {
            perror("Failed to reallocate memory for plugins array");
            // 尝试调用 unload (如果 dlsym 成功)
            PluginUnloadFunc unload = (PluginUnloadFunc)dlsym(dl_handle, "plugin_unload_export");
            if (unload) unload(plugin_handle);
            dlclose(dl_handle);
            return NULL;
        }
         manager->plugins = new_plugins_ptr;
    }

    // 7. 填充 LoadedPlugin 结构
    LoadedPlugin* new_plugin = &manager->plugins[manager->plugin_count]; // 先获取指针
    memset(new_plugin, 0, sizeof(LoadedPlugin)); // 清零结构体

    new_plugin->info.name = strdup_custom(info.name);
    new_plugin->info.description = strdup_custom(info.description);
    if (new_plugin->info.name == NULL || new_plugin->info.description == NULL) {
        perror("Failed to duplicate plugin info strings");
        free((void*)new_plugin->info.name); // free(NULL) is safe
        free((void*)new_plugin->info.description);
        PluginUnloadFunc unload = (PluginUnloadFunc)dlsym(dl_handle, "plugin_unload_export");
        if (unload) unload(plugin_handle);
        dlclose(dl_handle);
        return NULL;
    }
    new_plugin->info.api_version = info.api_version;
    new_plugin->handle = plugin_handle;
    new_plugin->state = PLUGIN_STATE_LOADED;
    new_plugin->dl_handle = dl_handle;
    new_plugin->config_node = config_node; // <--- 保存配置节点
    new_plugin->magic_number = 0x12345678;

    manager->plugin_count++; // 最后增加计数

    // --- 移除对 load_plugin_config 的调用 ---
    /*
    if (!load_plugin_config(manager, new_plugin, plugin_name)) {
        fprintf(stderr, "Failed to load plugin config for %s\n", plugin_name);
    }
    */

    return plugin_handle;
}

// --- 修改后的 unload_plugin ---
bool unload_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = NULL;
    int plugin_index = -1;

    // 查找插件并记录索引
    for (int i = 0; i < manager->plugin_count; ++i) {
        if (manager->plugins[i].handle == handle && manager->plugins[i].state != PLUGIN_STATE_UNLOADED) {
            plugin = &manager->plugins[i];
            plugin_index = i;
            break;
        }
    }

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found or already unloaded.\n", handle);
        return false; // 明确表示失败
    }

    // 检查幻数
    if (plugin->magic_number != 0x12345678) {
        fprintf(stderr, "Magic number corrupted for plugin %s! Memory corruption detected!\n", plugin->info.name ? plugin->info.name : "N/A");
        // 可能不安全继续，但尝试标记为卸载
        plugin->state = PLUGIN_STATE_UNLOADED;
        return false;
    }

    if (plugin->state == PLUGIN_STATE_STARTED) {
        stop_plugin(manager, handle); // 先停止插件
    }

    // 获取 unload 函数指针
    PluginUnloadFunc unload = (PluginUnloadFunc)dlsym(plugin->dl_handle, "plugin_unload_export");
    if (!unload) {
        fprintf(stderr, "Failed to find plugin_unload function for unloading %s, error: %s\n", plugin->info.name, dlerror());
        // 即使找不到 unload，也要继续尝试关闭句柄和释放内存
    } else {
        printf("Calling unload for plugin: %s\n", plugin->info.name);
        unload(handle); // 调用插件的 unload
    }

    printf("Closing dl handle for plugin: %s\n", plugin->info.name);
    dlclose(plugin->dl_handle);
    plugin->dl_handle = NULL;

    // 释放复制的插件信息
    printf("Freeing info strings for plugin: %s\n", plugin->info.name);
    free((void*)plugin->info.name);
    free((void*)plugin->info.description);
    plugin->info.name = NULL;
    plugin->info.description = NULL;

    // --- 移除对 plugin->config.param2 的释放 ---
    /*
    if(plugin->config.param2){
        free((void*)plugin->config.param2);
    }
    */

    plugin->handle = NULL;
    plugin->state = PLUGIN_STATE_UNLOADED;
    mpack_node_nil(plugin->config_node); // 清空节点引用
    plugin->magic_number = 0; // 清除幻数

    // 可选：从数组中移除插件（如果需要保持数组紧凑）
    // 这会使 PluginHandle 失效，如果外部持有 handle 则需要注意
    /*
    if (plugin_index != -1 && plugin_index < manager->plugin_count - 1) {
        memmove(&manager->plugins[plugin_index],
                &manager->plugins[plugin_index + 1],
                sizeof(LoadedPlugin) * (manager->plugin_count - 1 - plugin_index));
    }
    manager->plugin_count--;
    // 可能需要 realloc 缩小数组容量
    */
    printf("Plugin %p marked as unloaded.\n", handle);
    return true; // 表示卸载过程（尝试）完成
}

// --- 修改后的 start_plugin ---
bool start_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = find_plugin(manager, handle);

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found for starting.\n", handle);
        return false;
    }

     // 检查幻数
    if (plugin->magic_number != 0x12345678) {
        fprintf(stderr, "Magic number corrupted before starting plugin %s!\n", plugin->info.name);
        return false;
    }

    if (plugin->state != PLUGIN_STATE_LOADED && plugin->state != PLUGIN_STATE_STOPPED) {
        fprintf(stderr, "Plugin %s cannot be started in its current state (%d).\n", plugin->info.name, plugin->state);
        return false;
    }

    // --- 获取 start 函数指针，注意签名变化 ---
    PluginStartFunc start = (PluginStartFunc)dlsym(plugin->dl_handle, "plugin_start_export");
    if (!start) {
        fprintf(stderr, "Failed to find plugin_start function for %s, error: %s\n", plugin->info.name, dlerror());
        return false;
    }
    printf("Found start function address %p for plugin %s\n", start, plugin->info.name);
    printf("Plugin handle value is %p\n", handle);
    printf("Passing config node to start...\n");

    // --- 调用 start 函数，传入配置节点 ---
    if (!start(handle, plugin->config_node)) { // <--- 传递 config_node
        fprintf(stderr, "Plugin %s failed to start.\n", plugin->info.name);
        return false;
    }

    plugin->state = PLUGIN_STATE_STARTED;
    printf("Started plugin: %s\n", plugin->info.name);
    return true;
}

// 停止插件 (保持不变，因为 stop 通常不需要配置)
void stop_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = find_plugin(manager, handle);

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found for stopping.\n", handle);
        return;
    }

     // 检查幻数
    if (plugin->magic_number != 0x12345678) {
        fprintf(stderr, "Magic number corrupted before stopping plugin %s!\n", plugin->info.name);
        return; // 可能不安全调用 stop
    }


    if (plugin->state != PLUGIN_STATE_STARTED) {
        fprintf(stderr, "Plugin %s is not running.\n", plugin->info.name);
        return;
    }

    PluginStopFunc stop = (PluginStopFunc)dlsym(plugin->dl_handle, "plugin_stop_export");
    if (!stop) {
        fprintf(stderr, "Failed to find plugin_stop function for %s, error: %s\n", plugin->info.name, dlerror());
        return;
    }

    printf("Calling stop for plugin: %s\n", plugin->info.name);
    stop(handle);
    plugin->state = PLUGIN_STATE_STOPPED;

    printf("Stopped plugin: %s\n", plugin->info.name);
}


// 启动所有已加载或已停止的插件
void start_all_plugins(PluginManager* manager) {
    if (!manager) return;
    printf("Starting all plugins...\n");
    for (int i = 0; i < manager->plugin_count; ++i) {
        LoadedPlugin* plugin = &manager->plugins[i];
        // 只有处于 LOADED 或 STOPPED 状态的插件才尝试启动
        if (plugin->state == PLUGIN_STATE_LOADED || plugin->state == PLUGIN_STATE_STOPPED) {
            printf("Attempting to start plugin: %s\n", plugin->info.name ? plugin->info.name : "N/A");
            if (!start_plugin(manager, plugin->handle)) {
                fprintf(stderr, "Warning: Failed to start plugin %s (handle %p).\n",
                        plugin->info.name ? plugin->info.name : "N/A", plugin->handle);
                // 根据需要决定是否继续启动其他插件
            }
        } else {
             printf("Skipping start for plugin %s (state: %d)\n",
                    plugin->info.name ? plugin->info.name : "N/A", plugin->state);
        }
    }
    printf("Finished starting all plugins.\n");
}

// 停止所有正在运行的插件
void stop_all_plugins(PluginManager* manager) {
    if (!manager) return;
    printf("Stopping all plugins...\n");
    // 从后往前停止，有时有助于处理依赖关系（虽然这里没有显式依赖）
    for (int i = manager->plugin_count - 1; i >= 0; --i) {
        LoadedPlugin* plugin = &manager->plugins[i];
        if (plugin->state == PLUGIN_STATE_STARTED) {
             printf("Attempting to stop plugin: %s\n", plugin->info.name ? plugin->info.name : "N/A");
            stop_plugin(manager, plugin->handle);
        } else {
            printf("Plugin %s is not running (state: %d).\n",
                   plugin->info.name ? plugin->info.name : "N/A", plugin->state);
        }
    }
     printf("Finished stopping all plugins.\n");
}